"""
规范解析服务

负责解析各种格式的规范文档并提取需求信息
"""

import re
import json
from pathlib import Path
from typing import List, Dict, Any, Optional
import markdown
from bs4 import BeautifulSoup
from modules.specification_fixer.utils.logger import get_logger

logger = get_logger(__name__)


class SpecificationParser:
    """规范文档解析器"""

    def __init__(self):
        """初始化解析器"""
        # 需求识别模式
        self.requirement_patterns = [
            r'^-\s*(.+)$',  # Markdown列表项
            r'^\d+\.\s*(.+)$',  # 数字列表
            r'^\*\s*(.+)$',  # 星号列表
            r'^(.+功能)[：:]\s*(.+)$',  # 功能描述
        ]

        # 分类关键词
        self.category_keywords = {
            "core": ["核心", "必须", "必要", "关键", "主要"],
            "non_core": ["非核心", "可选", "辅助", "次要", "支持"],
            "optional": ["可选", "扩展", "增强", "附加"]
        }

        # 优先级关键词
        self.priority_keywords = {
            "high": ["高", "重要", "紧急", "P1", "必须"],
            "medium": ["中", "一般", "普通", "P2"],
            "low": ["低", "次要", "可选", "P3"]
        }

    def parse_requirements(self, file_path: str) -> List[Dict[str, Any]]:
        """解析规范文件提取需求"""
        file_path = Path(file_path)
        if not file_path.exists():
            raise FileNotFoundError(f"规范文件不存在: {file_path}")

        try:
            # 读取文件内容
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()

            # 根据文件类型解析
            if file_path.suffix.lower() == '.md':
                return self._parse_markdown(content)
            elif file_path.suffix.lower() in ['.txt', '.text']:
                return self._parse_text(content)
            elif file_path.suffix.lower() == '.json':
                return self._parse_json(content)
            else:
                # 默认尝试Markdown解析
                logger.warning(f"未知文件类型 {file_path.suffix}，尝试Markdown解析")
                return self._parse_markdown(content)

        except Exception as e:
            logger.error(f"解析规范文件失败: {e}")
            raise ValueError(f"无法解析规范文件: {e}")

    def _parse_markdown(self, content: str) -> List[Dict[str, Any]]:
        """解析Markdown格式规范"""
        requirements = []
        current_section = ""
        requirement_id = 0

        lines = content.split('\n')
        i = 0

        while i < len(lines):
            line = lines[i].strip()

            # 跳过空行和标题
            if not line or line.startswith('#'):
                if line.startswith('#'):
                    current_section = self._extract_section_title(line)
                i += 1
                continue

            # 尝试匹配需求模式
            requirement = self._extract_requirement_from_line(line, current_section)
            if requirement:
                requirement['id'] = f"req_{requirement_id:03d}"
                requirement['section'] = current_section
                requirement['line_number'] = i + 1

                # 检查是否有续行
                description = requirement['description']
                j = i + 1
                while j < len(lines) and self._is_continuation_line(lines[j]):
                    description += " " + lines[j].strip()
                    j += 1

                requirement['description'] = description.strip()
                requirements.append(requirement)
                requirement_id += 1
                i = j
            else:
                i += 1

        logger.info(f"从Markdown解析出 {len(requirements)} 个需求")
        return requirements

    def _parse_text(self, content: str) -> List[Dict[str, Any]]:
        """解析纯文本格式规范"""
        requirements = []
        requirement_id = 0

        lines = content.split('\n')
        for i, line in enumerate(lines):
            line = line.strip()
            if not line:
                continue

            requirement = self._extract_requirement_from_line(line)
            if requirement:
                requirement['id'] = f"req_{requirement_id:03d}"
                requirement['line_number'] = i + 1
                requirements.append(requirement)
                requirement_id += 1

        logger.info(f"从文本解析出 {len(requirements)} 个需求")
        return requirements

    def _parse_json(self, content: str) -> List[Dict[str, Any]]:
        """解析JSON格式规范"""
        try:
            data = json.loads(content)
            requirements = []

            # 处理不同的JSON结构
            if isinstance(data, list):
                requirements = data
            elif isinstance(data, dict):
                if 'requirements' in data:
                    requirements = data['requirements']
                elif 'features' in data:
                    requirements = data['features']
                else:
                    # 将字典的值作为需求
                    for key, value in data.items():
                        if isinstance(value, str):
                            requirements.append({
                                'description': value,
                                'title': key
                            })
                        elif isinstance(value, dict):
                            requirements.append({
                                'id': key,
                                **value
                            })

            # 标准化需求格式
            standardized_requirements = []
            for i, req in enumerate(requirements):
                if isinstance(req, str):
                    standardized_requirements.append({
                        'id': f"req_{i:03d}",
                        'description': req
                    })
                elif isinstance(req, dict):
                    if 'id' not in req:
                        req['id'] = f"req_{i:03d}"
                    standardized_requirements.append(req)

            logger.info(f"从JSON解析出 {len(standardized_requirements)} 个需求")
            return standardized_requirements

        except json.JSONDecodeError as e:
            raise ValueError(f"JSON格式错误: {e}")

    def _extract_requirement_from_line(self, line: str, section: str = "") -> Optional[Dict[str, Any]]:
        """从单行文本中提取需求"""
        for pattern in self.requirement_patterns:
            match = re.match(pattern, line)
            if match:
                description = match.group(1) if match.groups() else match.group(0)
                return self._create_requirement_object(description, section)

        return None

    def _create_requirement_object(self, description: str, section: str = "") -> Dict[str, Any]:
        """创建需求对象"""
        requirement = {
            'description': description,
            'section': section,
            'category': self._classify_requirement(description),
            'priority': self._determine_priority(description),
            'keywords': self._extract_keywords(description)
        }

        # 尝试提取标题
        title_match = re.match(r'^(.+?)[：:]\s*(.+)$', description)
        if title_match:
            requirement['title'] = title_match.group(1).strip()
            requirement['description'] = title_match.group(2).strip()

        return requirement

    def _classify_requirement(self, description: str) -> str:
        """对需求进行分类"""
        desc_lower = description.lower()

        # 检查核心功能关键词
        if any(keyword in desc_lower for keyword in self.category_keywords["core"]):
            return "core"

        # 检查非核心功能关键词
        if any(keyword in desc_lower for keyword in self.category_keywords["non_core"]):
            return "non_core"

        # 检查可选功能关键词
        if any(keyword in desc_lower for keyword in self.category_keywords["optional"]):
            return "optional"

        # 基于内容推断
        if any(keyword in desc_lower for keyword in ["文档", "分析", "评估", "需求"]):
            return "core"
        elif any(keyword in desc_lower for keyword in ["资产", "管理", "账号", "密码"]):
            return "non_core"

        return "unknown"

    def _determine_priority(self, description: str) -> str:
        """确定需求优先级"""
        desc_lower = description.lower()

        # 检查优先级关键词
        for priority, keywords in self.priority_keywords.items():
            if any(keyword in desc_lower for keyword in keywords):
                return priority

        # 基于分类推断优先级
        category = self._classify_requirement(description)
        if category == "core":
            return "high"
        elif category == "non_core":
            return "medium"
        else:
            return "low"

    def _extract_keywords(self, description: str) -> List[str]:
        """提取关键词"""
        # 简单的关键词提取（基于常见技术词汇）
        keyword_patterns = [
            r'文档\w*',
            r'分析\w*',
            r'管理\w*',
            r'功能\w*',
            r'系统\w*',
            r'用户\w*',
            r'数据\w*',
            r'接口\w*',
            r'服务\w*',
            r'模块\w*'
        ]

        keywords = []
        for pattern in keyword_patterns:
            matches = re.findall(pattern, description)
            keywords.extend(matches)

        return list(set(keywords))

    def _extract_section_title(self, header_line: str) -> str:
        """提取章节标题"""
        # 移除Markdown标题标记
        title = re.sub(r'^#+\s*', '', header_line).strip()
        return title

    def _is_continuation_line(self, line: str) -> bool:
        """判断是否为续行"""
        stripped = line.strip()
        if not stripped:
            return False

        # 如果不是列表项开头，可能是续行
        return not (stripped.startswith('-') or
                   stripped.startswith('*') or
                   re.match(r'^\d+\.', stripped))

    def parse_structure(self, file_path: str) -> Dict[str, Any]:
        """解析规范文档结构"""
        file_path = Path(file_path)
        if not file_path.exists():
            raise FileNotFoundError(f"规范文件不存在: {file_path}")

        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()

        structure = {
            'file_path': str(file_path),
            'file_size': len(content),
            'sections': [],
            'total_lines': len(content.split('\n')),
            'format': file_path.suffix.lower()
        }

        # 解析章节结构
        lines = content.split('\n')
        current_section = None
        section_start = 0

        for i, line in enumerate(lines):
            if line.startswith('#'):
                if current_section:
                    current_section['line_count'] = i - section_start
                    structure['sections'].append(current_section)

                current_section = {
                    'title': self._extract_section_title(line),
                    'level': len(line) - len(line.lstrip('#')),
                    'line_start': i + 1,
                    'subsections': []
                }
                section_start = i

        # 添加最后一个章节
        if current_section:
            current_section['line_count'] = len(lines) - section_start
            structure['sections'].append(current_section)

        return structure

    def validate_specification(self, file_path: str) -> Dict[str, Any]:
        """验证规范文档质量"""
        try:
            requirements = self.parse_requirements(file_path)
            structure = self.parse_structure(file_path)

            validation_result = {
                'is_valid': True,
                'issues': [],
                'warnings': [],
                'metrics': {
                    'total_requirements': len(requirements),
                    'sections_count': len(structure['sections']),
                    'core_requirements': len([r for r in requirements if r.get('category') == 'core']),
                    'non_core_requirements': len([r for r in requirements if r.get('category') == 'non_core'])
                }
            }

            # 检查问题
            if len(requirements) == 0:
                validation_result['issues'].append("未找到任何需求")
                validation_result['is_valid'] = False

            if len(structure['sections']) == 0:
                validation_result['warnings'].append("文档没有章节结构")

            core_ratio = validation_result['metrics']['core_requirements'] / len(requirements) if requirements else 0
            if core_ratio < 0.3:
                validation_result['warnings'].append("核心功能比例较低，可能需要重新评估范围")

            return validation_result

        except Exception as e:
            return {
                'is_valid': False,
                'issues': [f"验证失败: {e}"],
                'warnings': [],
                'metrics': {}
            }